﻿<!-- HTML for static distribution bundle build -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>%(DocumentTitle)</title>
    <link rel="stylesheet" type="text/css" href="./swagger-ui.css">
    <link rel="icon" type="image/png" href="./favicon-32x32.png" sizes="32x32"/>
    <link rel="icon" type="image/png" href="./favicon-16x16.png" sizes="16x16"/>
    <style>

        html {
            box-sizing: border-box;
            overflow: -moz-scrollbars-vertical;
            overflow-y: scroll;
        }

        *,
        *:before,
        *:after {
            box-sizing: inherit;
        }

        body {
            margin: 0;
            background: #fafafa;
        }

        #login-form {
            position: fixed;
            top: 30px;
            left: 50%;
            margin-left: -191px;
            width: 382px;
            display: none;
            border-color: #49cc90;
            background: rgba(73, 204, 144, .1);
            border: 1px solid #000;
            border-radius: 4px;
            box-shadow: 0 0 3px rgb(0 0 0 / 19%);
            font-family: monospace;
            overflow: hidden;
        }

        .login-title {
            background-color: rgb(27, 27, 27);
            height: 50px;
            padding: 7px 0 0 7px;
        }

        .login-title img {
            display: block;
            height: 36px;
        }

        .login-area {
            padding: 25px 40px 32px;
            background-color: rgb(232, 246, 240);
        }

        .form-row {
            padding: 6px 0;
        }

        .form-row label {
            font-size: 14px;
            flex: 1;
            margin: 0;
            font-family: sans-serif;
            color: #3b4151;
            font-weight: 700;
        }

        .form-row input {
            width: 100%;
            max-width: 340px;
            min-width: 100px;
            margin: 5px 0;
            padding: 8px 10px;
            border: 1px solid #d9d9d9;
            border-radius: 4px;
            background: #fff;
        }

        .form-row button {
            padding: 8px 40px;
            font-size: 14px;
            border: none;
            outline: none;
            font-weight: 700;
            cursor: pointer;
            border-radius: 3px;
            background-color: #4990e2;
            color: #fff;
            border-color: #4990e2;
            box-shadow: 0 0 5px rgb(0 0 0 / 30%);
            width: 100%;
            box-sizing: border-box;
        }

        .form-row button:hover {
            opacity: 0.8;
        }

        #login-error {
            font-size: 14px;
            flex: 1;
            margin: 0;
            font-family: sans-serif;
            color: red;
            margin-top: 8px;
        }
    </style>
    %(HeadContent)
</head>

<body>
<div id="swagger-ui"></div>
<div id="login-form">
    <div class="login-title">
        <img src=""
             alt=""/>
    </div>
    <div class="login-area">
        <div class="form-row">
            <label for="userName">User Name: </label>
            <input type="text" id="userName" name="userName"/>
        </div>
        <div class="form-row">
            <label for="password">Password: </label>
            <input type="password" id="password" name="password"/>
        </div>
        <div class="form-row" style="display: %(useTenantName)">
            <label for="tenantName">TenantName: </label>
            <input type="text" id="tenantName" name="tenantName"/>
        </div>
        <div class="form-row">
            <label></label>
            <button id="submit">Submit</button>
        </div>
        <div id="login-error"></div>
    </div>
</div>
<!-- Workaround for https://github.com/swagger-api/swagger-editor/issues/1371 -->
<script>
    if (window.navigator.userAgent.indexOf("Edge") > -1) {
        console.log("Removing native Edge fetch in favor of swagger-ui's polyfill")
        window.fetch = undefined;
    }
</script>

<script src="./swagger-ui-bundle.js"></script>
<script src="./swagger-ui-standalone-preset.js"></script>
<script>
    /* Source: https://gist.github.com/lamberta/3768814
     * Parse a string function definition and return a function object. Does not use eval.
     * @param {string} str
     * @return {function}
     *
     * Example:
     *  var f = function (x, y) { return x * y; };
     *  var g = parseFunction(f.toString());
     *  g(33, 3); //=> 99
     */
    function parseFunction(str) {
        if (!str) return void (0);

        var fn_body_idx = str.indexOf('{'),
            fn_body = str.substring(fn_body_idx + 1, str.lastIndexOf('}')),
            fn_declare = str.substring(0, fn_body_idx),
            fn_params = fn_declare.substring(fn_declare.indexOf('(') + 1, fn_declare.lastIndexOf(')')),
            args = fn_params.split(',');

        args.push(fn_body);

        function Fn() {
            return Function.apply(this, args);
        }

        Fn.prototype = Function.prototype;

        return new Fn();
    }

    // get uri all query variables
    function getQueryVariables(uri) {
        var searchArgs = window.location.search;
        if (uri) {
            var s = uri.indexOf('?');
            searchArgs = s > -1 ? uri.substring(s) : '';
        }
        var query = searchArgs.substring(1);
        var vars = query.split('&');
        var varObj = {};
        for (var i = 0; i < vars.length; i++) {
            var pair = vars[i].split('=');
            varObj[pair[0]] = pair[1];
        }
        return varObj;
    }

    // get uri query variable
    function getQueryVariable(variable, uri) {
        var vars = getQueryVariables(uri);
        for (var key in vars) {
            if (key === variable) return vars[key];
        }
        return (false);
    }

    // if value is null or undefined than execute delete operate, else execute update
    function updateQueryVariable(uri, key, value) {
        var re = new RegExp('([?&])' + key + '=.*?(&|$)', 'i');
        var separator = uri.indexOf('?') !== -1 ? '&' : '?';
        if (uri.match(re)) {
            return uri.replace(re, !value ? '' : ('$1' + key + '=' + value + '$2'));
        } else {
            return !value ? '' : (uri + separator + key + '=' + value);
        }
    }

    // get uri template
    function getUrlTemplate(uri) {
        var reg = /\{(.+?)\}/g;
        return uri.match(reg);
    }

    // hide empty tags
    var HideEmptyTagsPlugin = function HideEmptyTagsPlugin() {
        return {
            statePlugins: {
                spec: {
                    wrapSelectors: {
                        taggedOperations: function taggedOperations(ori) {
                            return function () {
                                return ori.apply(void 0, arguments).filter(function (tagMeta) {
                                    return tagMeta.get("operations") && tagMeta.get("operations").size > 0;
                                });
                            };
                        }
                    }
                }
            }
        };
    };

    var tokenKey = "access-token";
    var cultureKey = "culture";
    var silkyResultStatusKey = "silky-result-status";

    // default response interceptor
    function defaultResponseInterceptor(response) {
        // handle jwt token
        var accessToken = response.headers[tokenKey];
        var silkyResultStatus = response.headers[silkyResultStatusKey];
        if (accessToken && accessToken != "invalid_token") {
            window.localStorage.setItem(tokenKey, accessToken);
            ui.preauthorizeApiKey("Bearer", accessToken);
        } else if (accessToken == "invalid_token") {
            window.localStorage.removeItem(tokenKey);
            ui.authActions.logout(["Bearer"]);
        } else if (silkyResultStatus &&
            (silkyResultStatus.toString() === "401" || silkyResultStatus.toString() === "4011"
                || silkyResultStatus.toString() === "UnAuthentication" || silkyResultStatus.toString() === "IssueTokenError")) {
            window.localStorage.removeItem(tokenKey);
            ui.authActions.logout(["Bearer"]);
        }

        return response;
    }

    // default request interceptor
    function defaultRequestInterceptor(request) {
        var url = request.url;

        // add swagger header
        request.headers["request-from"] = "swagger";

        // handle template
        var temps = getUrlTemplate(url);
        if (temps && temps.length > 0) {
            for (var i = 0; i < temps.length; i++) {
                var temp = temps[i];
                var key = temp.substring(1, temp.length - 1);
                var queryKey = getQueryVariable(key, url);
                if (queryKey) {
                    url = updateQueryVariable(url.replace(temp, queryKey), key);
                } else url = url.replace(temp, '');
            }
            request.url = url;
        }

        // handle culture lang
        var culture = getQueryVariable(cultureKey);
        if (culture && culture.length > 0) {
            request.url = updateQueryVariable(url, cultureKey, culture);
        }

        return request;
    }

    // send ajax request
    function sendRequest(params) {
        let xhr = new XMLHttpRequest();
        xhr.onreadystatechange = function () {
            if (xhr.readyState == 4 && xhr.status == 200) {
                let obj = JSON.parse(xhr.response);
                let headers = xhr.getAllResponseHeaders();
                let arr = headers.trim().split(/[\r\n]+/);
                let headerMap = {};
                arr.forEach(function (line) {
                    let parts = line.split(': ');
                    let header = parts.shift();
                    let value = parts.join(': ');
                    headerMap[header] = value;
                });

                params.success(obj, headerMap);
            } else if (xhr.readyState == 4 && xhr.status >= 400) {
                params.error(xhr);
            }
            if (xhr.readyState == 1) {
                let requestMap = {};
                requestMap.url = params.url;
                requestMap.headers = {};
                if (params.beforeSend) {
                    params.beforeSend(requestMap);
                }
                for (let key in requestMap.headers) {
                    xhr.setRequestHeader(key, requestMap.headers[key])
                }
            }
        }

        function objectToString(obj) {
            let arr = [];
            for (var k in obj) {
                arr.push(`${k}=${obj[k]}`);
            }

            return arr.join('&');
        }

        let qs = objectToString(params.data);

        let accessToken = window.localStorage.getItem(tokenKey);

        if (params.method.toUpperCase() == 'GET') {
            xhr.open('GET', params.url + '?' + qs);
            if (accessToken) {
                xhr.setRequestHeader('Authorization', 'Bearer ' + accessToken);
            }
            xhr.send();
        } else if (params.method.toUpperCase() == 'POST') {
            xhr.open('POST', params.url);
            xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
            if (accessToken) {
                xhr.setRequestHeader('Authorization', 'Bearer ' + accessToken);
            }
            xhr.send(qs);
        }
    }

    // init swagger ui
    function initSwaggerUI(configObject, oauthConfigObject) {
        configObject.onComplete = function () {
            var accessToken = window.localStorage.getItem(tokenKey);
            if (accessToken) {
                ui.preauthorizeApiKey("Bearer", accessToken);
            }
        };

        // Workaround for https://github.com/swagger-api/swagger-ui/issues/5945
        configObject.urls.forEach(function (item) {
            if (item.url.startsWith("http") || item.url.startsWith("/")) return;
            item.url = window.location.href.replace("index.html", item.url).split('#')[0];
        });

        // If validatorUrl is not explicitly provided, disable the feature by setting to null
        if (!configObject.hasOwnProperty("validatorUrl"))
            configObject.validatorUrl = null

        // If oauth2RedirectUrl isn't specified, use the built-in default
        if (!configObject.hasOwnProperty("oauth2RedirectUrl"))
            configObject.oauth2RedirectUrl = (new URL("oauth2-redirect.html", window.location.href)).href;

        // Apply mandatory parameters
        configObject.dom_id = "#swagger-ui";
        configObject.presets = [SwaggerUIBundle.presets.apis, SwaggerUIStandalonePreset, HideEmptyTagsPlugin];
        configObject.layout = "StandaloneLayout";

        // Parse and add interceptor functions
        var interceptors = JSON.parse('%(Interceptors)');
        if (interceptors.RequestInterceptorFunction)
            configObject.requestInterceptor = parseFunction(interceptors.RequestInterceptorFunction);
        if (interceptors.ResponseInterceptorFunction)
            configObject.responseInterceptor = parseFunction(interceptors.ResponseInterceptorFunction);

        // Begin Swagger UI call region

        const ui = SwaggerUIBundle(configObject);

        ui.initOAuth(oauthConfigObject);

        // End Swagger UI call region

        window.ui = ui
    }

    window.onload = function () {
        var configObject = JSON.parse('%(ConfigObject)');
        var oauthConfigObject = JSON.parse('%(OAuthConfigObject)');

        var loginObject = configObject.LoginInfo;
        if (loginObject && loginObject.enabled === true) {
            var loginForm = document.getElementById("login-form");
            var userName = document.getElementById("userName");
            var password = document.getElementById("password");
            var tenantName = document.getElementById("tenantName");
            var submit = document.getElementById("submit");
            var loginError = document.getElementById("login-error");
            loginForm.style.display = "block";

            sendRequest({
                method: "POST",
                url: loginObject.checkUrl,
                success: function (res, headerMap) {
                    if (res.toString() === "200") {
                        loginForm.style.display = "none";
                        initSwaggerUI(configObject, oauthConfigObject);
                    } else {
                        userName.focus();

                        submit.addEventListener("click", function (ev) {
                            if (userName.value.trim().length === 0) {
                                userName.focus();
                                return;
                            }
                            if (password.value.trim().length === 0) {
                                password.focus();
                                return;
                            }

                            loginError.innerHTML = "";

                            sendRequest({
                                method: "POST",
                                url: loginObject.submitUrl,
                                data: {
                                    userName: userName.value.trim(),
                                    password: password.value.trim(),
                                    tenantName: tenantName?.value
                                },
                                beforeSend: function (request) {
                                    defaultRequestInterceptor(request)
                                },
                                success: function (res, headerMap) {
                                    if (res.toString() === "200") {
                                        loginForm.style.display = "none";
                                        initSwaggerUI(configObject, oauthConfigObject);
                                        defaultResponseInterceptor({headers: headerMap});
                                    } else {
                                        loginError.innerHTML = "Invalid UserName or Password.";
                                    }
                                },
                                error: function (xhr) {
                                    if (xhr.status === 404) {
                                        loginError.innerHTML = "Not Found: " + loginObject.submitUrl;
                                    }
                                    else if (xhr.status === 401 || xhr.status === 403) {
                                        loginError.innerHTML = "Token is invalid or timed out ";
                                    }
                                    else {
                                        loginError.innerHTML = "Internal ServerError: " + loginObject.submitUrl;
                                    }
                                }
                            });
                        });
                    }
                },
                error: function (xhr) {
                    if (xhr.status === 404) {
                        loginError.innerHTML = "Not Found: " + loginObject.checkUrl;
                    }
                    else if (xhr.status === 401 || xhr.status === 403) {
                        loginError.innerHTML = "Token is invalid or timed out ";
                    }
                    else {
                        loginError.innerHTML = "Internal ServerError: " + loginObject.checkUrl;
                    }
                    window.localStorage.removeItem(tokenKey);
                    if (ui) {
                        ui.authActions.logout(["Bearer"]);
                    }
                }
            });


        } else {
            initSwaggerUI(configObject, oauthConfigObject);
        }
    }
</script>
</body>
</html>